粗解PageHelper分页逻辑 |
您所在的位置:网站首页 › pagenum pagesize › 粗解PageHelper分页逻辑 |
起因
在学习若依管理系统的过程中,发现其系统的几乎没有分页的代码,很是疑惑。发现其使用了一个名为PageHelper的中间件,通过实现mybatis拦截器,拦截执行分页SQL,从而来实现后台分页功能,那么这个PageHelper的实现原理是什么样的?我们来粗略的探究一下。 参数获取与传递与保存在学习的过程中,发现若依系统中出现分页时,在Controller层并没有编写如下获取分页参数的方法,例如: @PreAuthorize("@ss.hasPermi('monitor:oper:list')") @GetMapping("/list") public TableDataInfo list(SysOper oper) { startPage(); // .... }那么分页参数是如何获取的呢?又是如何传递给后续SQL的呢? 我们发现每次分页都与startPage()方法有关,猜测分页参数大概是在startPage()函数中获取的。看一下startPage源码: /** * 设置请求分页数据 */ protected void startPage() { PageDomain pageDomain = TableSupport.buildPageRequest(); Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize(); if (StringUtils.isNotNull(pageNum) && StringUtils.isNotNull(pageSize)) { String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy()); Boolean reasonable = pageDomain.getReasonable(); PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable); } }可以清楚地看到其中有两行: Integer pageNum = pageDomain.getPageNum(); Integer pageSize = pageDomain.getPageSize();查看其基础逻辑为通过TableSupport.buildPageRequest()构造一个PageDomain对象,其中通过: getRequest().getParameter(name);达到获取请求中的分页参数的目的。 那么后续分页参数是如何传递的呢? 作者使用了一个非常巧妙的对象:ThreadLocal。通过使用ThreadLocal保存分页的参数,以便后续使用。这个对象通常被称为线程局部变量。 我们来看一下逐层的逻辑,上述的startPage在最后一句调用: PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);其方法内部为: /** * 基础分页方法 * * @author liuzh */ public abstract class PageMethod { /** * 开始分页 * * @param pageNum 页码 * @param pageSize 每页显示数量 * @param count 是否进行count查询 * @param reasonable 分页合理化,null时用默认配置 * @param pageSizeZero true且pageSize=0时返回全部结果,false时分页,null时用默认配置 */ public static Page startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) { Page page = new Page(pageNum, pageSize, count); page.setReasonable(reasonable); page.setPageSizeZero(pageSizeZero); //当已经执行过orderBy的时候 Page oldPage = getLocalPage(); if (oldPage != null && oldPage.isOrderByOnly()) { page.setOrderBy(oldPage.getOrderBy()); } setLocalPage(page); return page; } }其中的关键是getLocalPage以及setLocalPage,我们来看一下这两个方法: /** * 基础分页方法 * * @author liuzh */ public abstract class PageMethod { protected static final ThreadLocal LOCAL_PAGE = new ThreadLocal(); /** * 设置 Page 参数 * * @param page */ protected static void setLocalPage(Page page) { LOCAL_PAGE.set(page); } /** * 获取 Page 参数 * * @return */ public static Page getLocalPage() { return LOCAL_PAGE.get(); } }在使用时,即可通过getLocalPage()方法获取到分页相关的参数。 总结线程局部变量之前我只在阿里巴巴的日期格式化编码规范中见过,没想到线程局部变量的功能会如此强大与巧妙。 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |